/***************************************************************************
 *   This file is part of "libaiml"                                        *
 *   Copyright (C) 2005 by V01D                                            *
 *                                                                         *
 *   "libaiml" is free software; you can redistribute it and/or modify     *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   "libaiml" is distributed in the hope that it will be useful,          *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with "libaiml"; if not, write to the                            *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <std_utils/std_util.h>
#include <fstream>
#include <iostream>
#include "../src/aiml.h"

using namespace std;
using std_util::strip;
using namespace aiml;

#ifdef WIN32
#include <windows.h> 

string GBKToUTF8(const std::string& strGBK)
{
	string strOutUTF8 = "";
	WCHAR * str1;
	int n = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0);
	str1 = new WCHAR[n];
	MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, str1, n);
	n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);
	char * str2 = new char[n];
	WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL);
	strOutUTF8 = str2;
	delete[]str1;
	str1 = NULL;
	delete[]str2;
	str2 = NULL;
	return strOutUTF8;
}


string UTF8ToGBK(const std::string& strUTF8)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, NULL, 0);
	unsigned short * wszGBK = new unsigned short[len + 1];
	memset(wszGBK, 0, len * 2 + 2);
	MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)strUTF8.c_str(), -1, (LPWSTR)wszGBK, len);

	len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wszGBK, -1, NULL, 0, NULL, NULL);
	char *szGBK = new char[len + 1];
	memset(szGBK, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wszGBK, -1, szGBK, len, NULL, NULL);
	std::string strTemp(szGBK);
	delete[] szGBK;
	szGBK = NULL;
	delete[] wszGBK;
	wszGBK = NULL;
	return strTemp;
}

#endif





class cTestAppCallbacks : public cInterpreterCallbacks {
  public:
    void onAimlLoad(const std::string& filename) {
      cout << "Loaded " << filename << endl;
    }
};

int main(int argc, char* argv[]) {
  cInterpreter* interpreter = cInterpreter::newInterpreter();

  int ret = 0;
  
  // exceptions are used because returning in the middle of the program wouldn't let 'interpreter' be freed
  try {
    cTestAppCallbacks myCallbacks;
    interpreter->registerCallbacks(&myCallbacks);
    
    cout << "Initializing interpreter..." << endl;
    if (!interpreter->initialize("libaiml.xml")) throw 1;
    
    string line;
    cout << "Type \"quit\" to... guess..." << endl;

    string result;
    std::list<cMatchLog> log;

    cout << "You: " << flush;
    while (getline(cin, line)) {
      if (strip(line).empty()) { cout << "You: " << flush; continue; }
      if (line == "quit") break;
      
#ifdef WIN32
	  line = GBKToUTF8(line);
#endif

      /** remove the last parameter to avoid logging the match **/
      if (!interpreter->respond(line, "localhost", result, &log))
		  throw 3;

#ifdef WIN32
	  result = UTF8ToGBK(result);
#endif

      cout << "Bot: " << strip(result) << endl;
      //cout << "Match path:" << endl;
      //for(list<cMatchLog>::const_iterator it_outter = log.begin(); it_outter != log.end(); ++it_outter) {
      //  cout << "\tpattern:\t";
      //  for (list<string>::const_iterator it = it_outter->pattern.begin(); it != it_outter->pattern.end(); ++it) { cout << "[" << *it << "] "; }
      //  cout << endl << "\tthat:\t\t";
      //  for (list<string>::const_iterator it = it_outter->that.begin(); it != it_outter->that.end(); ++it) { cout << "[" << *it << "] "; }
      //  cout << endl << "\ttopic:\t\t";
      //  for (list<string>::const_iterator it = it_outter->topic.begin(); it != it_outter->topic.end(); ++it) { cout << "[" << *it << "] "; }
      //  cout << endl << endl;
      //}
      cout << "You: " << flush;
    }
  
    /** Uncomment this line out and you'll see that the bot will no longer remember user vars **/
    //interpreter->unregisterUser("localhost");
  }
  catch(int _ret) {
    cout << "ERROR: " << interpreter->getErrorStr(interpreter->getError()) << " (" << interpreter->getError() << ")" << endl;
    if (!interpreter->getRuntimeErrorStr().empty()) cout << "Runtime Error: " << interpreter->getRuntimeErrorStr() << endl;
    ret = _ret;
  }

  delete interpreter;
  // the above is equivalent to cInterpreter::freeInterpreter(interpreter);
  return ret;
}
